const { ethers } = require('ethers');
require('dotenv').config();

/**
 * Metadata更新解决方案
 * 处理IPFS文件不可变性的问题
 */

// 配置信息
const CONFIG = {
    // 当前的IPFS文件夹hash
    currentIPFSHash: "QmYP7zPrdxLPeJ4h3YghxYZ7YYn3dYjF1R25TxfG9cG3jn",

    // 新的IPFS文件夹hash（重新上传后）
    newIPFSHash: "YOUR_NEW_IPFS_HASH_HERE",

    // 网络配置
    rpcUrl: process.env.SEPOLIA_RPC_URL,
    privateKey: process.env.PRIVATE_KEY,

    // 合约地址
    contractAddress: "YOUR_CONTRACT_ADDRESS_HERE"
};

// 合约ABI
const CONTRACT_ABI = [
    "function setBaseURI(string memory newBaseURI) public",
    "function baseURI() public view returns (string)",
    "function setTokenURI(uint256 tokenId, string memory _tokenURI) public",
    "function tokenURI(uint256 tokenId) public view returns (string)",
    "function totalSupply() public view returns (uint256)",
    "function ownerOf(uint256 tokenId) public view returns (address)"
];

class MetadataUpdater {
    constructor() {
        this.provider = null;
        this.wallet = null;
        this.contract = null;
    }

    async initialize() {
        console.log("🚀 初始化Metadata更新器...");

        // 检查配置
        if (CONFIG.contractAddress === "YOUR_CONTRACT_ADDRESS_HERE") {
            throw new Error("请先设置合约地址！");
        }

        // 初始化provider和wallet
        this.provider = new ethers.providers.JsonRpcProvider(CONFIG.rpcUrl);
        this.wallet = new ethers.Wallet(CONFIG.privateKey, this.provider);

        // 初始化合约
        this.contract = new ethers.Contract(
            CONFIG.contractAddress,
            CONTRACT_ABI,
            this.wallet
        );

        console.log("✅ 初始化完成");
        console.log(`📝 钱包地址: ${this.wallet.address}`);
        console.log(`🔗 合约地址: ${CONFIG.contractAddress}`);
    }

    /**
     * 方案1: 重新上传整个文件夹
     */
    async solution1_ReuploadFolder() {
        console.log("\n🔄 方案1: 重新上传整个文件夹");
        console.log("-" * 40);

        if (CONFIG.newIPFSHash === "YOUR_NEW_IPFS_HASH_HERE") {
            console.log("❌ 请先重新上传IPFS文件夹并设置新的hash");
            console.log("📋 步骤:");
            console.log("1. 修改本地metadata文件中的image字段");
            console.log("2. 重新上传整个IPFS文件夹");
            console.log("3. 获得新的文件夹hash");
            console.log("4. 在CONFIG.newIPFSHash中设置新hash");
            return;
        }

        try {
            // 更新baseURI
            const newBaseURI = `ipfs://${CONFIG.newIPFSHash}/`;
            console.log(`📤 更新baseURI: ${newBaseURI}`);

            const tx = await this.contract.setBaseURI(newBaseURI);
            console.log(`⏳ 交易哈希: ${tx.hash}`);
            await tx.wait();
            console.log("✅ baseURI更新成功");

            // 验证
            const currentBaseURI = await this.contract.baseURI();
            console.log(`📋 当前baseURI: ${currentBaseURI}`);

            console.log("\n🎉 方案1完成！");
            console.log("💡 现在新铸造的NFT将使用新的IPFS hash");

        } catch (error) {
            console.error("❌ 方案1失败:", error.message);
        }
    }

    /**
     * 方案2: 单独上传修改后的metadata文件
     */
    async solution2_UploadIndividualFiles() {
        console.log("\n📁 方案2: 单独上传修改后的metadata文件");
        console.log("-" * 40);

        console.log("📋 步骤:");
        console.log("1. 修改本地metadata文件中的image字段");
        console.log("2. 单独上传修改后的metadata文件到IPFS");
        console.log("3. 获得新的metadata文件hash");
        console.log("4. 使用新的hash铸造NFT");

        console.log("\n💡 示例:");
        console.log("// 修改后的metadata文件单独上传");
        console.log("// 获得新hash: QmNewMetadataHash123...");
        console.log("// 铸造时使用:");
        console.log("await contract.mintNFT(recipient, 'ipfs://QmNewMetadataHash123...');");
    }

    /**
     * 方案3: 更新已铸造NFT的URI
     */
    async solution3_UpdateExistingNFTs() {
        console.log("\n🔄 方案3: 更新已铸造NFT的URI");
        console.log("-" * 40);

        try {
            const totalSupply = await this.contract.totalSupply();
            console.log(`📊 总供应量: ${totalSupply}`);

            if (totalSupply.toNumber() === 0) {
                console.log("ℹ️  还没有铸造任何NFT");
                return;
            }

            // 示例：更新第一个NFT的URI
            const tokenId = 1;
            const newMetadataHash = "QmNewMetadataHash123..."; // 请替换为实际hash

            console.log(`🔄 更新Token ${tokenId}的URI...`);
            console.log(`📤 新URI: ipfs://${newMetadataHash}`);

            // 注意：这里需要实际的newMetadataHash
            if (newMetadataHash === "QmNewMetadataHash123...") {
                console.log("❌ 请先设置实际的新metadata hash");
                console.log("📋 步骤:");
                console.log("1. 修改metadata文件");
                console.log("2. 单独上传到IPFS");
                console.log("3. 获得新hash");
                console.log("4. 在newMetadataHash中设置");
                return;
            }

            const tx = await this.contract.setTokenURI(tokenId, `ipfs://${newMetadataHash}`);
            console.log(`⏳ 交易哈希: ${tx.hash}`);
            await tx.wait();
            console.log("✅ Token URI更新成功");

            // 验证
            const tokenURI = await this.contract.tokenURI(tokenId);
            console.log(`📋 更新后URI: ${tokenURI}`);

        } catch (error) {
            console.error("❌ 方案3失败:", error.message);
        }
    }

    /**
     * 显示当前状态
     */
    async showCurrentStatus() {
        console.log("\n📊 当前状态");
        console.log("-" * 20);

        try {
            const baseURI = await this.contract.baseURI();
            const totalSupply = await this.contract.totalSupply();

            console.log(`📋 当前baseURI: ${baseURI}`);
            console.log(`📊 总供应量: ${totalSupply}`);

            if (totalSupply.toNumber() > 0) {
                console.log("\n🔍 已铸造NFT的URI:");
                for (let i = 1; i <= totalSupply; i++) {
                    try {
                        const tokenURI = await this.contract.tokenURI(i);
                        console.log(`   Token ${i}: ${tokenURI}`);
                    } catch (error) {
                        console.log(`   Token ${i}: 查询失败`);
                    }
                }
            }

        } catch (error) {
            console.error("❌ 查询状态失败:", error.message);
        }
    }

    /**
     * 运行所有解决方案
     */
    async runAllSolutions() {
        console.log("🎯 Metadata更新解决方案");
        console.log("=" * 50);

        try {
            await this.initialize();
            await this.showCurrentStatus();

            // 运行所有方案
            await this.solution1_ReuploadFolder();
            await this.solution2_UploadIndividualFiles();
            await this.solution3_UpdateExistingNFTs();

            console.log("\n📋 总结:");
            console.log("=" * 20);
            console.log("✅ 方案1: 重新上传整个文件夹（推荐）");
            console.log("✅ 方案2: 单独上传修改后的文件");
            console.log("✅ 方案3: 更新已铸造NFT的URI");

            console.log("\n💡 推荐使用方案1，因为:");
            console.log("- 保持文件结构一致");
            console.log("- 便于管理");
            console.log("- 新铸造的NFT自动使用新hash");

        } catch (error) {
            console.error("❌ 执行失败:", error.message);
        }
    }
}

// 使用示例
async function main() {
    const updater = new MetadataUpdater();
    await updater.runAllSolutions();
}

// 如果直接运行此脚本
if (require.main === module) {
    main().catch(console.error);
}

module.exports = { MetadataUpdater, CONFIG };
